#include "map.hpp"
#include "rescue.hpp"
#include "sim.hpp"
#include "../utils/utils.hpp"
#include <cstring>

int main(int argc, char *argv[]) {
	if (argc < 4)
		fatal("usage: sim <alg> <nnodes> <deadline> [-m <maxpeople>] [-s <seed>] [-nsamp <nsamples for hindsight>] [-noreuse]");

	const char *alg = argv[1];

	uint64_t seed = walltime() * 1e9;

	char *end = NULL;
	unsigned int nnodes = strtoul(argv[2], &end, 10);
	if (end == argv[2])
		fatal("bad nnodes: %s", argv[2]);

	double deadline = strtod(argv[3], &end);
	if (end == argv[3])
		fatal("bad deadline: %s", argv[3]);

	unsigned int nsamp = 16;
	bool reuse = true;
	bool southonly = false;
	bool westonly = false;

	dfheader(stdout);

	for (int i = 4; i < argc; i++) {
		if (i < argc-1 && strcmp(argv[i], "-s") == 0) {
			char *end = NULL;
			seed = strtol(argv[++i], &end, 10);
			if (end == argv[i])
				fatal("bad seed value: %s", argv[i]);

		} else if (i < argc-1 && strcmp(argv[i], "-m") == 0) {
			char *end = NULL;
			MaxPeople = strtol(argv[++i], &end, 10);
			if (end == argv[i])
				fatal("bad max people value: %s", argv[i]);

		} else if (i < argc-1 && strcmp(argv[i], "-nsamp") == 0) {
			if (strcmp(alg, "hindsight") != 0)
				fatal("nsamp only valid for hindsight");
			char *end = NULL;
			nsamp = strtol(argv[++i], &end, 10);
			if (end == argv[i])
				fatal("bad nsamp value: %s", argv[i]);

		} else if (strcmp(argv[i], "-noreuse") == 0) {
			if (strcmp(alg, "hindsight") != 0)
				fatal("noreuse only valid for hindsight");
			reuse = false;

		} else if (strcmp(argv[i], "-south") == 0) {
			southonly = true;

		} else if (strcmp(argv[i], "-west") == 0) {
			westonly = true
;
		} else {
			fatal("Unknown option: %s", argv[i]);
		}
	}

	fprintf(stderr, "seed=%lu\n", (unsigned long) seed);	
	randgen = Rand(seed);

	Rescue w = Rescue(Map(), std::vector<int>(), 0, deadline);
	w.southonly = southonly;
	w.westonly = westonly;
	w = w.future(nnodes);

	Planner *p = NULL;
	if (strcmp(alg, "oracle") == 0) {
		p = new Oracle(w);
	} else if (strcmp(alg, "hindsight") == 0) {
		p = new Hindsight(nsamp, nnodes, reuse);
	} else if (strcmp(alg, "depthfirst") == 0) {
		p = new DepthFirst();
	} else {
		fatal("Unknown algorithm: %s", alg);
	}

	sim(w, p);

	dfpair(stdout, "seed", "%lu", (unsigned long) seed);
	dfpair(stdout, "max people", "%lu", (unsigned long) MaxPeople);

	if (!southonly && !westonly)
		dfpair(stdout, "bias", "%s", "none");
	else if (southonly && westonly)
		dfpair(stdout, "bias", "%s", "southwest");
	else if (southonly)
		dfpair(stdout, "bias", "%s", "south");
	else if (westonly)
		dfpair(stdout, "bias", "%s", "west");

	if (strcmp(alg, "hindsight") == 0) {
		dfpair(stdout, "number of samples", "%u", nsamp);
		if (reuse)
			dfpair(stdout, "reuse samples", "%s", "true");
		else
			dfpair(stdout, "reuse samples", "%s", "false");
	}
	dffooter(stdout);
}